<template>
  <div
    class="up-swiper-box"
    @touchstart="touchStart"
    @touchmove="touchMove"
    @touchend="touchEnd"
    @click.stop=""
  >
    <div v-if="!isTab" class="up-swiper-content" :style="height" ref="upSwiper">
      <!-- <div v-for="(item, index) in banner" class="up-swiper-item" :key="index">
        <img class="up-swiper-item-img" :src="item.src" alt="" />
      </div> -->
      <slot />
    </div>
    <div v-if="isTab" class="up-swiper-content" :style="height" ref="upSwiper">
      <slot />
    </div>
    <div class="up-swiper-circle" v-if="showIndicators">
      <span
        v-for="(item, index) in swiperItemCount"
        :class="currentIndex == item ? 'up-swiper-item-active' : ''"
        @click="clickItem(item)"
        :key="index"
        ></span>
    </div>
  </div>
</template>

<script setup>
import { defineProps, ref, onMounted, nextTick, onBeforeMount, defineExpose } from 'vue'
import bus from '../utils/bus'
const props = defineProps({
  loop: {
    type: Boolean,
    default: true
  },
  width: {
    type: String,
    default: ''
  },
  height: {
    type: String,
    default: 'height: 200px;'
  },
  autoplay: {
    type: Boolean,
    default: true
  },
  duration: {
    type: Number,
    default: 2000
  },
  vertical: {
    type: Boolean,
    default: false
  },
  isTouch: {
    type: Boolean,
    default: true
  },
  isTab: {
    type: Boolean,
    default: false
  },
  isCascader: {
    type: Boolean,
    default: false
  },
  showIndicators: {
    type: Boolean,
    default: true
  },
  swipeName: {
    type: String,
    default: ''
  }
})

const upSwiper = ref(null)
const swiperItemCount = ref(0)
const swiperStyle = ref(0)
const currentIndex = ref(0)
const moveRatio = ref(0.25)
const totalWidth = ref(0)
const startX = ref(0)
const distance = ref(0)
const currentX = ref(0)
const times = ref(0)
const limitEdge = ref(false)
const isMove = ref(false)
let playTimer = null

// 设置滚动位置, 手指滑动，内容跟着动
const setTransform = (position) => {
  swiperStyle.value.transform = `translateX(${position}px)`
  swiperStyle.value['-webkit-transform'] = `translateX(${position}px)`
  swiperStyle.value['-ms-transform'] = `translateX(${position}px)`
}

// 设置滚动过渡动画
const setTransition = () => {
  swiperStyle.value.transition = 'transform 300ms'
}

// 循环dom 先拷贝一份
const handleDom = () => {
  const swiper = upSwiper.value
  swiperItemCount.value = swiper.children.length
  // 复制第一张图片和最后一张图片，分别放在最后面和最前面
  const nodeLast = swiper.children[swiperItemCount.value - 1].cloneNode(true)
  const nodeFirst = swiper.children[0].cloneNode(true)
  swiper.appendChild(nodeFirst)
  // // 如果 cloneNode 报错，那么只能在 dom 中直接添加最后一个图片了
  swiper.insertBefore(nodeLast, swiper.children[0])
  swiperStyle.value = swiper.style
  totalWidth.value = swiper.getBoundingClientRect().width
  // currentIndex 的初始值为 1 ，那么先显示第二张图片
  if (times.value === 0) { // 初始化时执行
    times.value = times.value + 1
    setTransform(-currentIndex.value * totalWidth.value) // 初始化的时候显示第二张
  } else {
    setTransform(currentIndex.value * totalWidth.value)
  }
}

// 非循环的则不用拷贝多一份
const unLoopHandleDom = () => {
  const swiper = upSwiper.value
  swiperItemCount.value = swiper.children.length
  swiperStyle.value = swiper.style
  totalWidth.value = swiper.getBoundingClientRect().width
}

const touchStart = (e) => {
  if (!props.isTouch) return
  totalWidth.value = upSwiper.value.getBoundingClientRect().width
  stopTimer()
  // 获取并保存开始触摸的位置
  startX.value = e.touches[0].pageX
}
const touchMove = (e) => {
  isMove.value = true
  if (!props.isTouch) return
  // 计算出用户拖动的距离
  currentX.value = e.touches[0].pageX
  distance.value = currentX.value - startX.value
  const currentPosition = -currentIndex.value * totalWidth.value
  const moveDistance = distance.value + currentPosition
  if (!props.loop) { // 禁止滚动时 最左最右的限制
    if (currentIndex.value === 0 && moveDistance >= 0) {
      limitEdge.value = true
    }
    if (currentIndex.value === upSwiper.value.children.length - 1 && moveDistance <= 0) {
      limitEdge.value = true
    }
  }
  // 设置当前的位置，也就是随着触摸移动，图片也跟随移动
  setTransform(moveDistance)
}
const touchEnd = (e) => {
  const distanceAbs = Math.abs(distance.value)
  if (!props.isTouch) return
  if (isMove.value === false) { // 点击触发
    if (props.loop) {
      swiperAuto()
    }
    return
  }
  if (distance.value === 0) {
    return
  } else if (distance.value < 0 && distanceAbs >= moveRatio.value * totalWidth.value) {
    if (currentIndex.value === upSwiper.value.children.length - 1 && limitEdge.value) {
      limitEdge.value = false
    } else {
      currentIndex.value++
      if (props.isTab) {
        sendContent(currentIndex.value)
      }
    }
  } else if (distance.value > 0 && distanceAbs >= moveRatio.value * totalWidth.value) {
    // 限制循环滚动时，到最左不能再左
    if (currentIndex.value === 0 && limitEdge.value) {
      limitEdge.value = false
    } else {
      currentIndex.value--
      if (props.isTab) {
        sendContent(currentIndex.value)
      }
    }
  }
  if (props.loop) {
    setTransition()
    setTransform(-currentIndex.value * totalWidth.value)
    currentScroll()
    swiperAuto()
  } else { // 限制循环滚动的
    setTransition()
    setTransform(-currentIndex.value * totalWidth.value)
    unLoopCurrentScroll()
  }
  isMove.value = false
}

// 3.判读第一张和最后一张图片的逻辑滚动，设置正确的滚动，抽取为函数
const currentScroll = () => {
  if (currentIndex.value === swiperItemCount.value + 1) {
    currentIndex.value = 1
  } else if (currentIndex.value === 0) {
    currentIndex.value = swiperItemCount.value
  }
  setTimeout(() => {
    swiperStyle.value.transition = '0ms'
    setTransform(-currentIndex.value * totalWidth.value)
  }, 300)
}

// 不让循环,滚动设置
const unLoopCurrentScroll = () => {
  setTimeout(() => {
    swiperStyle.value.transition = '0ms'
    setTransform(-currentIndex.value * totalWidth.value)
  }, 300)
}

// 4. 实现点击小圆圈跳转相应的图片
const clickItem = (item) => {
  if (!props.showIndicators) return
  stopTimer()
  currentIndex.value = item
  setTransform(-currentIndex.value * totalWidth.value)
  swiperAuto()
}

// 5.设置定时器，实现轮播功能
const swiperAuto = () => {
  // isMove.value = true
  playTimer = setInterval(() => {
    currentIndex.value++
    setTransition()
    setTransform(-currentIndex.value * totalWidth.value)
    currentScroll()
  }, props.duration)
}

const stopTimer = () => {
  clearInterval(playTimer)
}

// 监听标题变了，切换内容当前是哪一个
bus.on('switchContent', data => {
  if (!props.isTab) {
    return
  }
  // console.log('props.swipeName', props.swipeName)
  // console.log('data.preName', data.preName)
  console.log('data.currentIndex', data.currentIndex)
  if (props.swipeName === data.preName) {
    currentIndex.value = data.currentIndex
    if (upSwiper.value) {
      totalWidth.value = upSwiper.value.getBoundingClientRect().width // 获取总宽
    }
    setTransition()
    setTransform(-currentIndex.value * totalWidth.value)
    unLoopCurrentScroll()
  }
})

// 切换
const changeSwipeContent = (index) => {
  // console.log('index==========', index)
  currentIndex.value = index + 1
  if (upSwiper.value) {
    totalWidth.value = upSwiper.value.getBoundingClientRect().width // 获取总宽
  }
  setTransition()
  setTransform(-currentIndex.value * totalWidth.value)
  unLoopCurrentScroll()
}

// 传递移动的内容
const sendContent = (index) => {
  if (!props.isTab) {
    return
  }
  console.log('被执行了')
  bus.emit('switchTitle', {
    currentIndex: index,
    preName: props.swipeName
  })
}

defineExpose({
  changeSwipeContent
})

onBeforeMount(() => {
  // handleDom()
})

onMounted(() => {
  if (props.loop) {
    nextTick(() => {
      handleDom()
    })
  } else {
    nextTick(() => {
      unLoopHandleDom()
    })
  }
  nextTick(() => {
    if (props.loop) {
      swiperAuto()
    }
  })
})
</script>

<style>
.up-swiper-box {
  position: relative;
  overflow: hidden;
  padding: 0;
  margin: 0;
}
.up-swiper-content {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
}
.up-swiper-item {
  float: left;
  width: 100%;
  flex-shrink: 0;
}
.up-swiper-item-img {
  float: left;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.up-swiper-circle {
  min-width: 50px;
  position: absolute;
  bottom: 8px;
  left: 50%;
  transform: translate(-50%, -50%);
  text-align: center;
}
.up-swiper-circle > span {
  list-style: none;
  float: left;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  margin: 0 3px;
  background-color: rgba(200, 200, 200, 0.5);
}
.up-swiper-circle .up-swiper-item-active {
  background-color: #1989fa;
  box-shadow: 0 0 2px 2px rgba(255, 255, 255, 0.5);
}
</style>
